package chess;

import java.util.ArrayList;

/**
 * Classe Position (Posição)
 * @author Beatriz Miho Anami
 * @author Lucas Rodrigues Anizelli
 * @author Marcos Okamura Rodrigues
 */
public class Position{
	private int row;
	private int column;
	
	/**
	 * Constante que representa um trajeto de linha.
	 */
	public static int ROW_PATH = 0;
	/**
	 * Constante que representa um trajeto de coluna.
	 */
	public static int COLUMN_PATH = 1;
	/**
	 * Constante que representa um trajeto de diagonal (\).
	 */
	public static int LEFT_DIAGONAL_PATH = 2;
	/**
	 * Constante que representa um trajeto de diagonal (/).
	 */
	public static int RIGHT_DIAGONAL_PATH = 3;
	/**
	 * Constante que representa um trajeto desconhecido.
	 */
	public static int UNKNOWN_PATH = 4;
	
	/**
	 * Constante que representa a primeira linha das brancas.
	 */
	public static int FIRST_WHITE_ROW = 0;
	/**
	 * Constante que representa a segunda linha das brancas.
	 */
	public static int SECOND_WHITE_ROW = 1;
	/**
	 * Constante que representa a primeira linha das brancas.
	 */
	public static int FIRST_BLACK_ROW = 7;
	/**
	 * Constante que representa a segunda linha das negras.
	 */
	public static int SECOND_BLACK_ROW = 6;
	
	/**
	 * Construtor da posição.
	 * @param row		linha da posição
	 * @param column	coluna da posição
	 */
	public Position(int row, int column){
		this.row = row;
		this.column = column;
	}

	/**
	 * Retorna a linha da posição.
	 * @return	linha da posição
	 */
	public int getRow(){
		return this.row;
	}

	/**
	 * Retorna a coluna da posição.
	 * @return	coluna da posição
	 */
	public int getColumn(){
		return this.column;
	}

	/**
	 * Retorna a representação da posição em formato de String.
	 * @return	representação da posição
	 */
	@Override
	public String toString(){
		return String.format("%c%d", this.column + 'a', this.row + 1);
	}
	
	/**
	 * Verifica se o objeto selecionado é igual a este objeto.
	 * @param object	objeto a ser comparado
	 * @return 			true se os objetos são iguais ou false caso contrário
	 */
	@Override
	public boolean equals(Object object){
		if(object == null || !(object instanceof Position)){
			return false;
		}
		Position position = (Position) object;
		return this.row == position.row && this.column == position.column;
	}
	
	/**
	 * Verifica se duas posições estão na mesma linha (-).
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				true se as duas posições estão na mesma linha ou false caso contrário
	 */
	public static boolean isSameRow(Position firstPosition, Position lastPosition){
		return firstPosition.row == lastPosition.row;
	}
	
	/**
	 * Verifica se duas posições estão na mesma coluna (|).
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				true se as duas posições estão na mesma coluna ou false caso contrário
	 */
	public static boolean isSameColumn(Position firstPosition, Position lastPosition){
		return firstPosition.column == lastPosition.column;
	}
	
	/**
	 * Verifica se duas posições estão na mesma diagonal (\).
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				true se as duas posições estão na mesma diagonal ou false caso contrário
	 */
	public static boolean isSameLeftDiagonal(Position firstPosition, Position lastPosition){
		return(firstPosition.row + firstPosition.column) 
			== (lastPosition.row + lastPosition.column);
	}
	
	/**
	 * Verifica se duas posições estão na mesma diagonal (/).
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				true se as duas posições estão na mesma diagonal ou false caso contrário
	 */
	public static boolean isSameRightDiagonal(Position firstPosition, Position lastPosition){
		return(firstPosition.row - firstPosition.column) 
			== (lastPosition.row - lastPosition.column);
	}
	
	/**
	 * Retorna o trajeto entre duas posições.
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				ArrayList de posições
	 */
	public static ArrayList<Position> getPath(Position firstPosition, Position lastPosition){
		ArrayList<Position> path = new ArrayList<Position>();
		if(Position.isSameRow(firstPosition, lastPosition)){
			return Position.getRowPath(firstPosition, lastPosition);
		} else if(Position.isSameColumn(firstPosition, lastPosition)){
			return Position.getColumnPath(firstPosition, lastPosition);
		} else if(Position.isSameLeftDiagonal(firstPosition, lastPosition)){
			return Position.getLeftDiagonalPath(firstPosition, lastPosition);
		} else if(Position.isSameRightDiagonal(firstPosition, lastPosition)){
			return Position.getRightDiagonalPath(firstPosition, lastPosition);
		} 
		return path;
	}
	
	/**
	 * Retorna o trajeto entre duas posições.
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				ArrayList de posições
	 */
	public static int getPathType(Position firstPosition, Position lastPosition){
		if(Position.isSameRow(firstPosition, lastPosition)){
			return ROW_PATH;
		} else if(Position.isSameColumn(firstPosition, lastPosition)){
			return COLUMN_PATH;
		} else if(Position.isSameLeftDiagonal(firstPosition, lastPosition)){
			return LEFT_DIAGONAL_PATH;
		} else if(Position.isSameRightDiagonal(firstPosition, lastPosition)){
			return RIGHT_DIAGONAL_PATH;
		} else {
			return UNKNOWN_PATH;
		}
	}
	
	/**
	 * Retorna o trajeto (linha -) entre duas posições.
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				ArrayList de posições
	 */
	public static ArrayList<Position> getRowPath(Position firstPosition, Position lastPosition){
		ArrayList<Position> path = new ArrayList<Position>();
		int firstColumn = Math.min(firstPosition.column, lastPosition.column);
		int lastColumn = Math.max(firstPosition.column, lastPosition.column);
		for(int column = firstColumn + 1; column < lastColumn; column++){
			path.add(new Position(firstPosition.row, column));
		}
		return path;
	}
	
	/**
	 * Retorna o trajeto (coluna |) entre duas posições.
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				ArrayList de posições
	 */
	public static ArrayList<Position> getColumnPath(Position firstPosition, Position lastPosition){
		ArrayList<Position> path = new ArrayList<Position>();
		int firstRow = Math.min(firstPosition.row, lastPosition.row);
		int lastRow = Math.max(firstPosition.row, lastPosition.row);
		for(int row = firstRow + 1; row < lastRow; row++){
			path.add(new Position(row, firstPosition.column));
		}
		return path;
	}
	
	/**
	 * Retorna o trajeto (diagonal \) entre duas posições.
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				ArrayList de posições
	 */
	public static ArrayList<Position> getLeftDiagonalPath(Position firstPosition, Position lastPosition){
		ArrayList<Position> arrayList = new ArrayList<Position>();
		int firstColumn, firstRow, lastRow;
		if(firstPosition.row < lastPosition.row){
			firstColumn = firstPosition.column;
			firstRow = firstPosition.row;
			lastRow = lastPosition.row;
		} else{
			firstColumn = lastPosition.column;
			firstRow = lastPosition.row;
			lastRow = firstPosition.row;
		}
		
		int row = firstRow + 1;
		int column = firstColumn - 1;
		while(row < lastRow){
			arrayList.add(new Position(row, column));
			row++;
			column--;
		}
		return arrayList;
	}
	
	/**
	 * Retorna o trajeto (diagonal /) entre duas posições.
	 * @param firstPosition	posição inicial
	 * @param lastPosition	posição final
	 * @return				ArrayList de posições
	 */
	public static ArrayList<Position> getRightDiagonalPath(Position firstPosition, Position lastPosition){
		ArrayList<Position> arrayList = new ArrayList<Position>();
		int firstColumn, firstRow, lastRow;
		if(firstPosition.row < lastPosition.row){
			firstColumn = firstPosition.column;
			firstRow = firstPosition.row;
			lastRow = lastPosition.row;
		} else{
			firstColumn = lastPosition.column;
			firstRow = lastPosition.row;
			lastRow = firstPosition.row;
		}
		
		int row = firstRow + 1;
		int column = firstColumn + 1;
		while(row < lastRow){
			arrayList.add(new Position(row, column));
			row++;
			column++;
		}
		return arrayList;
	}
}

